]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
status/network: Add NMSectionItem subclass
authorFlorian Müllner <fmuellner@gnome.org>
Tue, 2 Aug 2022 12:04:46 +0000 (14:04 +0200)
committerMarge Bot <marge-bot@gnome.org>
Wed, 10 Aug 2022 12:17:19 +0000 (12:17 +0000)
The class implements a menu item that contains a section which
can be collapsed into a submenu.

It is very common for network devices to only have one associated
connection, so hiding away a single item in a submenu is fairly
inconvenient.

This class will address this, by only using a submenu when it is
actually needed.

Although the main issue it addresses is that menus (including
sections) aren't GObjects. This gives us a GObject that can
be added to a menu, and that can itself contain other menu
items.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2407>

js/ui/status/network.js

index 394fd074e7dd18d0e325ca0977c23e65f9ff48e5..4d5f737888a74a3e07b4155c0d14d36d097a7e0c 100644 (file)
@@ -200,6 +200,78 @@ const NMMenuItem = GObject.registerClass({
     }
 });
 
+/**
+ * Item that contains a section, and can be collapsed
+ * into a submenu
+ */
+const NMSectionItem = GObject.registerClass({
+    Properties: {
+        'use-submenu': GObject.ParamSpec.boolean('use-submenu', '', '',
+            GObject.ParamFlags.READWRITE,
+            false),
+    },
+}, class NMSectionItem extends NMMenuItem {
+    constructor() {
+        super({
+            activate: false,
+            can_focus: false,
+        });
+
+        this._useSubmenu = false;
+
+        // Turn into an empty container with no padding
+        this.styleClass = '';
+        this.setOrnament(PopupMenu.Ornament.HIDDEN);
+
+        // Add intermediate section; we need this for submenu support
+        this._mainSection = new PopupMenu.PopupMenuSection();
+        this.add_child(this._mainSection.actor);
+
+        this._submenuItem = new PopupMenu.PopupSubMenuMenuItem('', true);
+        this._mainSection.addMenuItem(this._submenuItem);
+        this._submenuItem.hide();
+
+        this.section = new PopupMenu.PopupMenuSection();
+        this._mainSection.addMenuItem(this.section);
+
+        // Represents the item as a whole when shown
+        this.bind_property('name',
+            this._submenuItem.label, 'text',
+            GObject.BindingFlags.DEFAULT);
+        this.bind_property('icon-name',
+            this._submenuItem.icon, 'icon-name',
+            GObject.BindingFlags.DEFAULT);
+    }
+
+    _setParent(parent) {
+        super._setParent(parent);
+        this._mainSection._setParent(parent);
+
+        parent?.connect('menu-closed',
+            () => this._mainSection.emit('menu-closed'));
+    }
+
+    get use_submenu() {
+        return this._useSubmenu;
+    }
+
+    set use_submenu(useSubmenu) {
+        if (this._useSubmenu === useSubmenu)
+            return;
+
+        this._useSubmenu = useSubmenu;
+        this._submenuItem.visible = useSubmenu;
+
+        if (useSubmenu) {
+            this._mainSection.box.remove_child(this.section.actor);
+            this._submenuItem.menu.box.add_child(this.section.actor);
+        } else {
+            this._submenuItem.menu.box.remove_child(this.section.actor);
+            this._mainSection.box.add_child(this.section.actor);
+        }
+    }
+});
+
 const NMConnectionItem = GObject.registerClass(
 class NMConnectionItem extends NMMenuItem {
     constructor(section, connection) {